﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Linq;

namespace agree
{
	public abstract partial class ChartControl<T, W> : ChartResources<W>
		where T : ChartControl<T, W>
		where W : struct, IProximalContext<W>
	{
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// each cell of the chart is a concurrent list of objects which implement the IChartObj interface
		/// </summary>
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		[DebuggerDisplay("{ToString(),nq}")]
		public abstract class _chart_cell : IEnumerable<IChartObj>
		{
			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			protected IChartObj m_last = null;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			public alib.Concurrency.cache_line cl1;

			[DebuggerBrowsable(DebuggerBrowsableState.Never)]
			public IChartObj m_first = null;

			public void Add(IChartObj po, ref long i)
			{
				if (m_first == null && Interlocked.CompareExchange(ref m_first, po, null) == null)
				{
					po.SetSequenceId(ref i);
				}
				else
				{
					IChartObj ml = m_last ?? m_first;
					while ((ml = ml.AddToList(po, ref i)) != null)
					{
					}
				}
				m_last = po;
			}

			public struct _enum : IEnumerator<IChartObj>
			{
				_chart_cell cc;
				IChartObj cur;

				public _enum(_chart_cell cc)
				{
					this.cc = cc;
					this.cur = null;
				}

				public bool MoveNext()
				{
					return (cur = cur == null ? cc.m_first : cur.Next) != null;
				}

				public IChartObj Current { get { return cur; } }
				object IEnumerator.Current { get { return cur; } }
				public void Reset() { this.cur = null; }
				public void Dispose() { cur = null; cc = null; }
			};

			public struct _enum_x : IEnumerator<IChartObj>
			{
				_chart_cell cc;
				IChartObj cur, exclude;

				public _enum_x(_chart_cell cc, IChartObj exclude)
				{
					this.cc = cc;
					this.exclude = exclude;
					this.cur = null;
				}

				public bool MoveNext()
				{
					cur = cur == null ? cc.m_first : cur.Next;
					while (cur != null)
					{
						if (cur != exclude)
							return true;
						cur = cur.Next;
					}
					return false;
				}

				public IChartObj Current
				{
					get { return cur; }
					set { cur = value; }
				}
				object IEnumerator.Current { get { return cur; } }
				public void Reset() { this.cur = null; }
				public void Dispose() { cur = exclude = null; cc = null; }
			};


			public IEnumerator<IChartObj> GetEnumerator() { return new _enum(this); }
			IEnumerator IEnumerable.GetEnumerator() { return new _enum(this); }
		};
	}
}
